home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
programr
/
dpmigcc5.zip
/
RSX
/
SOURCE
/
SYSDJ.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-12-12
|
15KB
|
624 lines
/*****************************************************************************
* FILE: sysdj.c *
* *
* DESC: *
* - int 0x21, ah=0xff djgpp syscall handler *
* *
* Copyright (C) 1993,1994 *
* Rainer Schnitker, Heeper Str. 283, 33607 Bielefeld *
* email: rainer@mathematik.uni-bielefeld.de *
* *
*****************************************************************************/
#include <stdlib.h>
#include <string.h>
#include "DPMI.H"
#include "RMLIB.H"
#include "PRINTF.H"
#include "TIMEDOS.H"
#include "STATEMX.H"
#include "PROCESS.H"
#include "SIGNALS.H"
#include "CDOSX32.H"
#include "ADOSX32.H"
#include "START32.H"
#include "COPY32.H"
#include "RSX.H"
#include "DOSERRNO.H"
#include "DJIO.H"
/*
** For DJGPP programs 1.00 - 1.09 (not coff files) with big segments (4 MB)
**
** move stack,data,bss,heap
** |-CCCCC---------------------------------SSSS-DDDD-HHH-|
** 0 ^0x400000
**
** to the end of text
** |-CCCCC-SSSS-DDDD-HHH-|
*/
void compress_memory(void)
{
DWORD movedmem, newhandle, newaddress;
DWORD r_esp = ESP & ~4095L;
/* check djgpp segment, and stack */
if (npz->data_start != 0x400000L || r_esp > npz->data_start)
return;
movedmem = npz->membytes - r_esp; /* memory to move */
if (r_esp - npz->stack_down < movedmem) /* enough space? */
return;
cpy32_32(DS, r_esp, DS, npz->stack_down, movedmem);
if (ResizeMem(npz->stack_down + movedmem, npz->memhandle, &newhandle,
&newaddress)) {
printf("error:resize memory block\n");
return;
}
if (npz->memaddress != newaddress) {
npz->memaddress = newaddress;
SetBaseAddress(npz->code32sel, npz->memaddress);
SetBaseAddress(npz->data32sel, npz->memaddress);
SetBaseAddress(npz->data32sel + sel_incr, npz->memaddress);
}
npz->p_flags |= PF_COMPRESS;
}
void uncompress_memory(void)
{
DWORD movedmem, newhandle, newaddress;
DWORD r_esp = ESP & ~4095L;
/* check djgpp segment, and stack */
if (npz->data_start != 0x400000L || !(npz->p_flags & PF_COMPRESS))
return;
if (ResizeMem(npz->membytes, npz->memhandle, &newhandle, &newaddress)) {
printf("Can't switch to parant process: ENOMEM\n");
shut_down(1);
}
if (npz->memaddress != newaddress) {
npz->memaddress = newaddress;
SetBaseAddress(npz->code32sel, npz->memaddress);
SetBaseAddress(npz->data32sel, npz->memaddress);
SetBaseAddress(npz->data32sel + sel_incr, npz->memaddress);
}
movedmem = npz->membytes - r_esp; /* memory to move */
cpy32_32(DS, npz->stack_down, DS, r_esp, movedmem);
npz->p_flags &= ~PF_COMPRESS;
}
void def_extention(char *dst, const char *ext)
{
int dot, sep;
dot = 0;
sep = 1;
while (*dst != 0)
switch (*dst++) {
case '.':
dot = 1;
sep = 0;
break;
case ':':
case '/':
case '\\':
dot = 0;
sep = 1;
break;
default:
sep = 0;
break;
}
if (!dot && !sep) {
*dst++ = '.';
strcpy(dst, ext);
}
}
char *search_path(char *file, char *path)
{
char *list, *end;
int i;
strcpy(path, file);
if (rm_access(path, 4) == 0)
return path;
list = getenv("PATH");
if (list != NULL)
for (;;) {
while (*list == ' ' || *list == '\t')
++list;
if (*list == 0)
break;
end = list;
while (*end != 0 && *end != ';')
++end;
i = end - list;
while (i > 0 && (list[i - 1] == ' ' || list[i - 1] == '\t'))
--i;
if (i != 0) {
memcpy(path, list, i);
if (list[i - 1] != '/' && list[i - 1] != '\\' && list[i - 1] != ':')
path[i++] = '\\';
strcpy(path + i, file);
if (rm_access(path, 4) == 0)
return path;
}
if (*end == 0)
break;
list = end + 1;
}
path[0] = 0;
return (char *) 0;
}
struct time32 {
DWORD secs, usecs;
};
struct tz32 {
DWORD offset, dst;
};
struct stat32 {
short st_dev, st_ino, st_mode, st_nlink, st_uid, st_gid, st_rdev,
st_align_for_DWORD;
long st_size, st_atime, st_mtime, st_ctime, st_blksize;
};
static int set_systime(unsigned long *gmt_seconds)
{
struct tm tm;
struct dos_time dt;
gmt2tm(gmt_seconds, &tm);
dt.dtime_hour = (char) tm.tm_hour;
dt.dtime_minutes = (char) tm.tm_min;
dt.dtime_seconds = (char) tm.tm_sec;
dt.dtime_hsec = 0;
rm_settime(&dt);
return 0;
}
static int make_tokens(char *argmem, char **argp)
{
int i;
int args=0;
argp[args++] = argmem;
for (i = 0; argmem[i] != '\0'; i++)
if (argmem[i] == ' ') {
argmem[i] = '\0';
if (argmem[i + 1] == ' ')
continue;
else if (argmem[i + 1] != '\0')
argp[args++] = (argmem + i + 1);
}
argp[args] = 0;
return args;
}
/*
** DJGPP 1.12 gcc compiler doesn't use this call
**
** RSX starts the new process instead of loading the extender + prg
*/
int sys_system(char *command, char **env)
{
char *argmem;
char **argp;
char exe[260];
int args, r, i;
r = strlen(command);
args = 0;
for ( i = r; i > 0 ; i--) {
if (command[i] == ' ')
args++;
}
argmem = (char *) malloc(r+1);
argp = (char **) malloc((args+3) * sizeof(char **));
if (argmem == NULL || argp == NULL) {
if (argmem != NULL)
free(argmem);
if (argp != NULL)
free(argp);
errno = EMX_ENOMEM;
return -1;
}
strcpy(argmem, command);
/* make strings from command; build argv */
args = make_tokens(argmem, argp);
/* check last argument, response file? */
if (args > 1 && argp[args - 1][0] == '@') {
int f, bytes;
char *s = &argmem[i + 2];
args--;
f = rm_open(argp[args] + 1, RM_O_RDONLY | RM_O_DENYWR);
bytes = rm_read(f, s, 900);
s[bytes] = 0;
rm_close(f);
argp[args++] = s;
for (i = 0; i < bytes; i++)
if (*(s + i) == 13 && *(s + i + 1) == 10) {
*(s + i) = 0;
if (i + 4 > bytes)
break;
argp[args++] = (s + i + 2);
}
else if (*(s + i) == ' ' && *(s + i + 1) > ' ') {
argp[args++] = (s + i + 2);
}
argp[args] = 0;
}
if (rm_access(argmem, 4)) {
if (!search_path(argmem, exe)) {
errno = EMX_ENOENT;
free(argmem);
free(argp);
return -1;
} else {
argp[0] = exe;
}
}
/* resize memory to the real used page */
compress_memory();
r = exec32(P_WAIT, argp[0], args, argp, org_envc, org_env);
/* if error, try a real-mode prg */
if (r == EMX_ENOEXEC)
r = realmode_prg(argp[0], &(argp[0]), org_env);
uncompress_memory();
free(argmem);
free(argp);
return r;
}
/*
** DJGPP 1.11 exec/spawn
** uses TRANSLATION services by DPMI to simulate 0x21 ah=9x4b
**
** RSX starts the new process instead of loading the extender + prg
*/
int simulate_go32_exec(void)
{
TRANSLATION tr;
DWORD offset;
WORD *pblock;
char **env;
char *name;
int z, args;
char *cmd;
static char cline[128];
cpy32_16(ES, EDI, & tr, sizeof(tr));
/* get pointer to program name */
tr.edx += (DWORD) tr.ds << 4;
offset = tr.edx - ((DWORD)ds16real << 4);
name = (char *)(UINT)offset;
/* get pointer to exec block */
tr.ebx += (DWORD) tr.es << 4;
offset = tr.ebx - ((DWORD)ds16real << 4);
pblock = (WORD *)(UINT)offset;
/* get args */
offset = ((DWORD) pblock[2] << 4) + (DWORD) pblock[1];
offset -= (DWORD) ds16real << 4;
cmd = (char *) ((UINT) offset + 1);
/* build comand line */
strcpy(cline, name);
z = strlen(cline);
for ( ; z < sizeof(cline) ; z++) {
cline[z] = *cmd;
if (cline[z] == 13)
break;
cmd++;
}
cline[z] = '\0';
/* environment */
if (pblock[0]) {
offset = (DWORD) pblock[0] << 4;
offset -= ((DWORD)ds16real << 4);
env = (char **)(UINT)offset;
}
else
env = org_env;
/*** just like go32 **************
npz->regs.eax = 0x300;
if (execute_dpmi_function())
r = -1;
else
r = (int) tr.eax & 0xFF;
*********************************/
if (strstr(cline, "!proxy")) {
/* go32 !proxy argc seg off seg off info */
char *param[12]; /* if more in future */
WORD *newargs;
make_tokens(cline, param);
args = hexstr2int(param[2]);
offset = (DWORD) (UINT) hexstr2int(param[3]) << 4;
offset -= ((DWORD)ds16real << 4);
newargs = (WORD *) ((UINT) offset + (UINT) hexstr2int(param[4]));
strcpy(iobuf, (char *) ((UINT)newargs[0] + (UINT)offset));
for ( z = 1; z < args; z++) {
strcat(iobuf, " ");
strcat(iobuf, (char *)((UINT)newargs[z] + (UINT)offset));
}
cmd = iobuf;
} else
cmd = cline;
/* but it's better to handle it self */
return sys_system(cmd, NULL);
}
static long my_daylight;
static long my_timezone;
int i_21_ff(void)
{
DWORD p1 = EBX, p2 = ECX;
int r, i, handle;
switch (AX & 0xff) { /* al=? */
case 1:
handle = get_empty_proc_filp();
if (handle < 0) {
EAX = EMX_EBADF;
return CARRY_ON;
}
strcpy32_16(DS, p1, iobuf); /* p1 -> iobuf */
r = dj_creat(iobuf);
if (r >= 0) {
npz->filp[handle]->f_mode = FMODE_READ | FMODE_WRITE;
npz->filp[handle]->f_doshandle = r;
npz->filp[handle]->f_op = & msdos_fop;
r = handle;
}
break;
case 2:
handle = get_empty_proc_filp();
if (handle < 0) {
EAX = EMX_EBADF;
return CARRY_ON;
}
strcpy32_16(DS, p1, iobuf); /* p1 -> iobuf */
i = (int) (UINT) p2;
r = dj_open(iobuf, i);
if (r >= 0) {
npz->filp[handle]->f_mode = FMODE_READ | FMODE_WRITE;
npz->filp[handle]->f_doshandle = r;
npz->filp[handle]->f_op = & msdos_fop;
r = handle;
}
break;
case 3: /* fstat */
{
struct stat32 statbuf32;
struct stat statbuf;
handle = get_dos_handle((WORD) p1);
if (handle < 0) {
EAX = EMX_EBADF;
return CARRY_ON;
} else
p1 = handle;
r = sys_fstat(handle, &statbuf);
if (r == -1) {
errno = doserror_to_errno(_doserrno);
break;
}
statbuf32.st_dev = (short) statbuf.st_dev;
statbuf32.st_ino = (short) statbuf.st_ino;
statbuf32.st_mode = (short) statbuf.st_mode;
statbuf32.st_nlink = (short) statbuf.st_nlink;
statbuf32.st_uid = 42;
statbuf32.st_gid = 42;
statbuf32.st_rdev = (short) statbuf.st_rdev;
statbuf32.st_size = statbuf.st_size;
statbuf32.st_atime = statbuf.st_atime;
statbuf32.st_mtime = statbuf.st_mtime;
statbuf32.st_ctime = statbuf.st_ctime;
statbuf32.st_blksize = 4096;
/* stat -> p2 */
cpy16_32(DS, p2, &statbuf32, (DWORD) sizeof(statbuf32));
}
break;
case 4: /* get time & day */
{
struct time32 time32;
struct tz32 tz32;
struct dos_date dd;
struct dos_time dt;
if (p2) {
tz32.offset = my_timezone;
tz32.dst = my_daylight;
cpy16_32(DS, p2, &tz32, (DWORD) sizeof(tz32));
}
if (p1) {
unsigned long gmt;
rm_getdate(&dd);
rm_gettime(&dt);
gmt = dos2gmt(&dd, &dt);
time32.secs = gmt;
time32.usecs = (DWORD) dt.dtime_hsec * 10;
cpy16_32(DS, p1, &time32, (DWORD) sizeof(time32));
}
r = 0;
}
break;
case 5: /* set time & day */
{
struct time32 time32;
struct tz32 tz32;
if (p2) {
cpy32_16(DS, p2, &tz32, (DWORD) sizeof(tz32));
my_timezone = tz32.offset;
my_daylight = (WORD) tz32.dst;
}
if (p1) {
cpy32_16(DS, p1, &time32, (DWORD) sizeof(time32));
set_systime((unsigned long *) &(time32.secs));
}
r = 0;
}
break;
case 6: /* stat */
{
struct stat32 statbuf32;
struct stat statbuf;
char fname[160];
memset(&statbuf, 0, sizeof(statbuf));
strcpy32_16(DS, p1, fname);
r = sys_stat(fname, &statbuf);
if (r == -1) {
errno = doserror_to_errno(_doserrno);
break;
}
statbuf32.st_dev = (short) statbuf.st_dev;
statbuf32.st_ino = (short) statbuf.st_ino;
statbuf32.st_mode = (short) statbuf.st_mode;
statbuf32.st_nlink = (short) statbuf.st_nlink;
statbuf32.st_uid = 42;
statbuf32.st_gid = 42;
statbuf32.st_rdev = (short) statbuf.st_rdev;
statbuf32.st_size = statbuf.st_size;
statbuf32.st_atime = statbuf.st_atime;
statbuf32.st_mtime = statbuf.st_mtime;
statbuf32.st_ctime = statbuf.st_ctime;
statbuf32.st_blksize = 512;
/* stat -> p2 */
cpy16_32(DS, p2, &statbuf32, (DWORD) sizeof(statbuf32));
}
break;
case 7:
strcpy32_16(DS, p1, iobuf);
r = sys_system(iobuf, NULL);
if (r) {
errno = r;
r = -1;
}
break;
case 8:
handle = get_dos_handle((WORD) p1);
if (handle < 0) {
EAX = EMX_EBADF;
return CARRY_ON;
} else
p1 = (long) handle;
i = rm_ioctl_getattr(handle);
if (p2 & 0x8000) /* O_BINARY */
i |= 0x20;
else
i &= ~0x20;
rm_ioctl_setattr(handle, i);
r = dj_setmode((int) p1, (int) p2);
break;
case 9:
strcpy32_16(DS, p1, iobuf); /* p1 -> iobuf */
r = dj_chmod(iobuf, (int) p2);
break;
case 10: /* DOS 0x4B */
r = simulate_go32_exec();
break;
default:
r = -1;
errno = EMX_EIO;
break;
} /* switch */
if (r == -1) {
EAX = errno;
return CARRY_ON;
} else {
EAX = (long) r;
return CARRY_OFF;
}
}
/* go32 debug functions */
#define EXTERNAL_DEBUGGER_EXECUTE 0
#define EXTERNAL_DEBUGGER_GETINFOPTR 1
typedef struct {
WORD version; /* set to version number of interface */
WORD a_tss_ofs; /* pointer to TSS for debugged program */
WORD a_tss_seg;
WORD filename_ofs; /* points to name of file being debugged */
WORD filename_seg;
WORD filename_len;
WORD areas_ofs; /* from paging.c */
WORD areas_seg;
DWORD app_base; /* linear base address of application */
DWORD dr[8]; /* debug registers, set when a_tss runs */
DWORD ansi_mode; /* if set, OK to emit ansi control codes */
} ExternalDebuggerInfo;
int i_21_fe(void)
{
puts("external debugger not supported");
do_exit4c(0);
return 0;
/*
ext_debug_info.version = EXTERNAL_DEBUGGER_VERSION;
ext_debug_info.a_tss_ofs = FP_OFF(&a_tss);
ext_debug_info.a_tss_seg = ourDSsel;
ext_debug_info.filename_ofs = FP_OFF(running_fname);
ext_debug_info.filename_seg = ourDSsel;
ext_debug_info.filename_len = strlen(running_fname);
ext_debug_info.areas_ofs = FP_OFF(&areas);
ext_debug_info.areas_seg = ourDSsel;
ext_debug_info.app_base = ARENA;
ext_debug_info.ansi_mode = use_ansi;
memset(ext_debug_info.dr, 32, 0);
*/
}